/*
 * @Description  : verilog code from HUIYU
 * @authorName   : GuoJi
 * @github       : https://github.com/guoji-kk
 * @gitee        : https://gitee.com/guoji13663585559
 * @email        : 13663585559@163.com
 * @version      : 1.0
 * @Date         : 2023-06-02 10:50:46
 * @LastEditTime : 2023-06-04 18:03:33
 */


module present_encryptor_top(data_o,data_i,data_load,key_load,clk,encry_ok);

input  wire[79:0] data_i; 
input  wire clk; 
input  wire key_load; 
input  wire data_load; 

output wire[63:0] data_o;
output reg encry_ok;

reg  [63 : 0] state; // 64-bit state of the cipher
reg  [4  : 0] round_counter; // 5-bit round-counter (from 1 to 31)
reg  [79 : 0] key; // 80-bit register holding the key and updates of the key

wire [63 : 0] round_key; // 64-bit round-key. The round-keys are derived from the key register
wire [63 : 0] sub_per_input; // 64-bit input to the substitution-permutation network
wire [63 : 0] sub_per_output; // 64-bit output of the substitution-permutation network
wire [79 : 0] key_update_output; // 80-bit output of the keyupdate procedure. This value replaces the value of the key register



sub_per present_cipher_sp(.data_o(sub_per_output),.data_i(sub_per_input)); 
    // instantion of  substitution and permutation module
    // this module is used 31 times iteratively

key_update present_cipher_key_update(.data_o(key_update_output),.data_i(key),.round_counter(round_counter)); 
    // instantiation of the key-update procedure
    // this module is used 31 times iteratively
    


assign round_key = key[79:16]; // iurrent round-key is the 64 left most bits of the key register

assign sub_per_input = state^round_key; // input to the Substitution-Permutation network is the cipher state xored by the round key

assign data_o = sub_per_input; // the output of the cipher will finally be one of the inputs to the Substitution-Permutation network.
                             // output will be valid when round-counter is 31



always @(posedge clk)
begin
    if(key_load) // loading the key
    begin
        key <= data_i;
    end
    else if(!key_load) // not loading the key
    begin
        if(data_load) // loading plaintext
        begin
            state <= data_i[63:0];
            encry_ok = 0;
            round_counter <= 5'b00001; // round_counter starts from 1 and ends at 31
        end
        else if(!data_load) // normal operation (neither loading the key nor loading the plaitext)
        begin      
            if(round_counter == 0)
            begin
              encry_ok =1;
            end            
            else begin
            round_counter <= round_counter + 1'b1; // round counter is increased by one
            state <= sub_per_output; // state is updated
            key <= key_update_output; // key register is updated
            end
        end
    end
    
end

endmodule